package net.media.datafw.utils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.media.datafw.DataException;
import net.media.datafw.model.Field;

public class ReflectionUtil {
	static Logger logger = LoggerFactory.getLogger(ReflectionUtil.class);

	public static ArrayList<? extends Field> getFields(Class<?> clazz, Class<? extends Field> fieldType) throws DataException {
		ArrayList<Field> fields = new ArrayList<Field>();

		Method[] methods = clazz.getMethods();
		if (methods != null) {
			for (int methodIdx = 0; methodIdx < methods.length; methodIdx++) {
				Method getMethod = methods[methodIdx];
				String getMethodName = getMethod.getName();
				if (getMethodName.startsWith("get")) {
					String fieldName = getMethodName.substring("get".length());
					for (int methodIdx1 = 0; methodIdx1 < methods.length; methodIdx1++) {
						Method setMethod = methods[methodIdx1];
						if (setMethod.getName().equals("set" + fieldName)) {
							try {
								Field field = fieldType.getConstructor(Method.class, Method.class).newInstance(getMethod, setMethod);
								fields.add(field);
							} catch (Exception e) {
								throw new DataException(e);
							}
						}
					}
				}
			}
		}
		return fields;
	}

	public static HashMap<String, Field> getFieldsAsHashMap(Class<?> clazz, Class<? extends Field> fieldType) throws DataException {
		HashMap<String, Field> fields = new HashMap<String, Field>();

		Method[] methods = clazz.getMethods();
		if (methods != null) {
			for (int methodIdx = 0; methodIdx < methods.length; methodIdx++) {
				Method getMethod = methods[methodIdx];
				String getMethodName = getMethod.getName();
				if (getMethodName.startsWith("get")) {
					String fieldName = getMethodName.substring("get".length());
					for (int methodIdx1 = 0; methodIdx1 < methods.length; methodIdx1++) {
						Method setMethod = methods[methodIdx1];
						if (setMethod.getName().equals("set" + fieldName)) {
							try {
								String key = String.valueOf(fieldName.charAt(0)).toLowerCase() + fieldName.substring(1);
								Field field = fieldType.getConstructor(Method.class, Method.class).newInstance(getMethod, setMethod);
								fields.put(key, field);
							} catch (Exception e) {
								throw new DataException(e);
							}
						}
					}
				}
			}
		}
		return fields;
	}

	public static Map<String, Method> getMethodsMap(Class<?> clazz) {
		Map<String, Method> thisClassMethods = new HashMap<String, Method>();
		Method[] methods = clazz.getMethods();
		for (int i = 0; i < methods.length; i++) {
			thisClassMethods.put(methods[i].getName(), methods[i]);
		}
		return thisClassMethods;
	}
}
